local UI={}
string = require 'string'
UI.__index=UI

local tileConfig={
    [2]={
        color="#776e65",
        size=64,
        background="#eee4da"
    },
    [4]={
        color="#776e65",
        size=64,
        background="#eee1c9"
    },
    [8]={
        color="#f9f6f2",
        size=64,
        background="#f3b27a"
    },
    [16]={
        color="#f9f6f2",
        size=64,
        background="#f69664"
    },
    [32]={
        color="#f9f6f2",
        size=64,
        background="#f77c5f"
    },
    [64]={
        color="#f9f6f2",
        size=64,
        background="#f75f3b"
    },
    [128]={
        color="#f9f6f2",
        size=48,
        background="#edd073"
    },
    [256]={
        color="#f9f6f2",
        size=48,
        background="#edcc62"
    },
    [512]={
        color="#f9f6f2",
        size=48,
        background="#edc950"
    },
    [1024]={
        color="#f9f6f2",
        size=32,
        background="#edc53f"
    },
    [2048]={
        color="#f9f6f2",
        size=32,
        background="#edc22e"
    },
}

function UI.new()
    local o = {}
    o.margin = 15
    o.xmargin = 15
    o.ymargin = 200
    o.space = 10
    o.size = 100
    o.width = 450
    o.height = 450
    o.actions = {}
    o.reset = nil
    o.config = tileConfig
    o.mouse = nil
    o.isRetryActive = false
    setmetatable(o, UI)
    return o
end

function UI:addAction(name, rect, f)
    self.actions[name] = {rect=rect, f=f}
end

function UI:removeAction(name)
    self.actions[name] = nil
end

function UI:buttonActions()
    self:addAction(
        'NewGame',
        self:newGameButtonRect(),
        function()
            self.reset()
        end)
    self:addAction(
        'Retry',
        self:retryButtonRect(),
        function()
            if self.isRetryActive then
                self.isRetryActive = false
                self.reset()
            end
        end)
end

function UI:background()
    self:setRGBColor(119, 110, 101)
    love.graphics.rectangle("fill", self.xmargin, self.ymargin, self.width, self.height, 4)
    self:setRGBColor(238, 228, 218, 0.35)
    local margin = 15
    local space = 10
    local size = 100
    for i=0,3,1 do
        for j=0,3,1 do
            love.graphics.rectangle(
                "fill",
                self.xmargin+self.space+i*(self.size+self.space),
                self.ymargin+self.space+j*(self.size+self.space),
                self.size,
                self.size
            )
        end
    end
end

function UI:drawTile(n, x, y)
    local config = self.config[n]
    love.graphics.setFont(self:newRegularFont(config.size))
    local font = love.graphics.getFont()
    local yOffset = (self.size-font:getHeight())/2
    self:setHexColor(config.background)
    love.graphics.rectangle("fill", x, y, self.size, self.size)
    self:setHexColor(config.color)
    love.graphics.printf("" .. n, x, y + yOffset, self.size, "center")
end

function UI:newBoldFont(size)
    return love.graphics.newFont('assets/Roboto-Bold.ttf', size)
end

function UI:newRegularFont(size)
    return love.graphics.newFont('assets/Roboto-Regular.ttf', size)
end

function UI:setHexColor(color)
    if string.len(color) ~= 7 then
        return nil
    end
    local r = tonumber(string.sub(color, 2, 3), 16) / 255.0
    local g = tonumber(string.sub(color, 4, 5), 16) / 255.0
    local b = tonumber(string.sub(color, 6, 7), 16) / 255.0
    love.graphics.setColor(r, g, b, 1)
end

function UI:setRGBColor(r, g, b, a)
    if a == nil then
        a = 1
    end
    love.graphics.setColor(r/255, g/255, b/255, a)
end

function UI:showNums(nums)
    love.graphics.setColor(1, 1, 1, 1)
    for i=1,4,1 do
        for j=1,4,1 do
            local n = nums[i][j]
            if n > 0 then
                local x = self.xmargin+self.space+(j-1)*(self.size+self.space)
                local y = self.ymargin+self.space+(i-1)*(self.size+self.space)
                self:drawTile(n, x, y)
            end
        end
    end
end

function UI:update(box)
    self:background()
    self:title()
    self:score(box.score)
    self:newGameButton()
    self:showNums(box.data)
    self:moves(box.moves)
end

function UI:title()
    self:setHexColor("#776e65")
    love.graphics.setFont(self:newBoldFont(96))
    love.graphics.print("2048", self.xmargin, self.margin + 10)
    love.graphics.setFont(self:newRegularFont(18))
    love.graphics.print("Join the tiles, get to 2048!", self.xmargin, 140)
end

function UI:moves(n)
    self:setHexColor("#776e65")
    love.graphics.setFont(self:newRegularFont(18))
    love.graphics.print(""..n .. " moves", self.xmargin, self.space + self.ymargin + self.height)
end

function UI:gameOver()
    self:setRGBColor(238,228,218,0.9)
    love.graphics.rectangle("fill", self.xmargin, self.ymargin, self.width, self.height)
    self:setHexColor("#776e65")
    love.graphics.setFont(self:newBoldFont(48))
    love.graphics.printf("Game over!", self.xmargin, self.ymargin+160, self.width, "center")
    self:retryButton()
end

function UI:gameWin()
    self:setRGBColor(237,194,46,0.5)
    love.graphics.rectangle("fill", self.xmargin, self.ymargin, self.width, self.height)
    self:setHexColor("#f9f6f2")
    love.graphics.setFont(self:newBoldFont(48))
    love.graphics.printf("You win!", self.xmargin, self.ymargin+160, self.width, "center")
    self:retryButton()
end


function UI:retryButton()
    self.isRetryActive = true
    local rect = self:retryButtonRect()
    self:setHexColor("#8f7a66")
    love.graphics.rectangle("fill", rect.x, rect.y, rect.width, rect.height)
    self:setHexColor("#f9f6f2")
    love.graphics.setFont(self:regularFont(18))
    local font = love.graphics.getFont()
    local yOffset = (rect.height-font:getHeight())/2
    love.graphics.printf("Try again", rect.x, rect.y+yOffset, rect.width, "center")
end

function UI:retryButtonRect()
    local width = 128
    local height = 40
    local x = (self.width - width) / 2
    local y = self.ymargin + 260
    return {x=x, y=y, width=width, height=height}
end

function UI:isMouseInRect(rect)
    if self.mouse.x >= rect.x
        and self.mouse.x <= rect.x + rect.width
        and self.mouse.y >= rect.y
        and self.mouse.y <= rect.y + rect.height
    then
        return true
    end
    return false
end

function UI:newGameButton()
    local rect = self:newGameButtonRect()
    if self.mouse ~= nil and self:isMouseInRect(rect) then
        self:setHexColor("#938D87")
    else
        self:setHexColor("#8f7a66")
    end
    love.graphics.rectangle("fill", rect.x, rect.y, rect.width, rect.height, 4)
    self:setHexColor("#f9f6f2")
    love.graphics.setFont(self:newRegularFont(18))
    local font = love.graphics.getFont()
    local yOffset = (rect.height-font:getHeight())/2
    love.graphics.printf("New Game", rect.x, rect.y+yOffset, rect.width, "center") 
end

function UI:newGameButtonAction()
    print('new game clicked')
end

function UI:newGameButtonRect()
    local x = 325
    local y = 130
    local width = 140
    local height = 40
    return {x=x, y=y, width=width, height=height}
end

function UI:score(n)
    if n == nil then
        n = 0
    end
    local x = 325
    local y = 40
    local width = 140
    local height = 60
    self:setHexColor('#bbada0')
    love.graphics.rectangle("fill", x, y, width, height, 4)
    love.graphics.setFont(self:newBoldFont(14))
    self:setHexColor('#eee4da')
    love.graphics.printf("SCORE", x, y+10, width, "center")
    love.graphics.setFont(self:newRegularFont(20))
    self:setHexColor('#f9f6f2')
    love.graphics.printf(""..n, x, y+30, width, "center")
end

function UI:click(x, y)
    for k, v in pairs(self.actions) do
        if x >= v.rect.x
          and x <= v.rect.x + v.rect.width
          and y >= v.rect.y
          and y <= v.rect.y + v.rect.height
        then
            v.f()
        end
    end
end

return UI